import { Suspense } from 'react';
import { firstToUpperCase, isPureObject } from '@/utils';
import type { ReactElement, ReactNode } from 'react';

type AnyObject = Record<PropertyKey, any>;
type ObjListType = { name: string; obj: AnyObject };

export function createTypeDom(originObj: AnyObject, options?: { optional?: boolean }) {
	const resList: ReactElement[] = [];
	const objList: ObjListType[] = [];

	// 取出每层对象类型数据
	function getEveryKindObj(origin: AnyObject, name: string) {
		const domInfo: ObjListType = { name: firstToUpperCase(name), obj: {} };

		for (const key in origin) {
			if (isPureObject(origin[key])) {
				domInfo.obj[key] = [firstToUpperCase(key)];
				getEveryKindObj(origin[key], key);
			} else if (Array.isArray(origin[key])) {
				for (const item of origin[key]) {
					if (isPureObject(item)) {
						getEveryKindObj(item, 'a');
					}
				}
			} else {
				domInfo.obj[key] = origin[key];
			}
		}
		objList.push(domInfo);
	}
	getEveryKindObj(originObj, 'Welcome');

	// 创建类型dom节点
	function createDom(origin: ObjListType) {
		const { name, obj } = origin;
		const domInfoList = [];
		for (const key in obj) {
			domInfoList.push(
				<div key={key}>
					&nbsp;&nbsp;
					<span className="type-key">{key}</span>
					{options.optional && <span className="type-optional">?</span>}
					<span className="operator">: </span>
					<span className="type-ts">
						{typeof obj[key] === 'object' ? obj[key] : typeof obj[key]}
					</span>
					<span>;</span>
				</div>
			);
		}
		resList.push(
			<Suspense key={resList.length}>
				{resList.length ? <div className="divider">{'\n'}</div> : false}
				<div className="start">
					<span className="type-interface">interface </span>
					<span className="type-name">{name} </span>
					<span>{'{'}</span>
				</div>
				{domInfoList}
				<div className="end">{'}'}</div>
			</Suspense>
		);
	}
	for (let i = objList.length - 1; i >= 0; i--) {
		if (isPureObject(objList[i])) {
			createDom(objList[i]);
		}
	}

	return resList;
}

// 判断数组元素是否为同一类型
// function arrayIdenticalType(arr: any[]) {
// 	if (!Array.isArray(arr) || arr.length === 0) return { is: false, type: null };
// 	let flog = true;
// 	let firstType: string = null;

// 	for (const item of arr) {
// 		if (firstType && typeof item !== firstType) {
// 			flog = false;
// 		} else {
// 			firstType = typeof item;
// 		}
// 	}

// 	return { is: flog, type: firstType };
// }

// function isNumberArray(arr: any[]) {
// 	if (!Array.isArray(arr)) return false;
// 	let flog = true;
// 	for (const item of arr) {
// 		if (typeof item !== 'number') {
// 			flog = false;
// 			break;
// 		}
// 	}
// 	return flog;
// }
function isStringArray(arr: any[]) {
	if (!Array.isArray(arr)) return false;
	let flog = true;
	for (const item of arr) {
		if (typeof item !== 'string') {
			flog = false;
			break;
		}
	}
	return flog;
}
function isObjectArray(arr: any[]) {
	if (!Array.isArray(arr)) return false;
	let flog = true;
	for (const item of arr) {
		if (typeof item !== 'object') {
			flog = false;
			break;
		}
	}
	return flog;
}
function isHasObjectArray(arr: any[]) {
	if (!Array.isArray(arr)) return false;
	let flog = false;
	for (const item of arr) {
		if (typeof item == 'object') {
			flog = true;
			break;
		}
	}
	return flog;
}

// ======================= V2 =======================
type ItemNodeInfo = {
	key: string;
	type: 'basic' | 'union' | 'arrUnion' | 'genericity' | 'object' | 'array';
	info: Set<string>;
};
type AllObjInfo = { name: string; obj: AnyObject };

export function createTypeNode(jsonData: AnyObject, options?: { optional?: boolean }) {
	// 保存最终的类型dom节点
	const resNodeList: ReactNode[] = [];
	// 保存json数据中所有的纯对象数据
	const pureObjList: AllObjInfo[] = [];
	// 映射所有对象的类型
	const allObjTypes: ItemNodeInfo[] = [];

	// 递归取出所有纯对象
	function getAllPureObject(origin: AnyObject, name = 'welcome') {
		const obj = {};
		for (const key in origin) {
			if (isPureObject(origin[key])) {
				allObjTypes.push({
					key: `${name}_${key}`,
					type: 'object',
					info: new Set<string>().add(firstToUpperCase(key))
				});
				obj[key] = typeof origin[key];
				getAllPureObject(origin[key], key);
			} else if (isObjectArray(origin[key])) {
				// 对象数组
				let margeArrObj = {};
				for (const item of origin[key]) {
					if (isPureObject(item)) {
						margeArrObj = { ...item, ...margeArrObj };
					}
				}
				const typeInfos = new Set<string>();
				origin[key].forEach((item: any) => {
					if (typeof item !== 'object') {
						typeInfos.add(typeof item);
					} else {
						typeInfos.add(`${firstToUpperCase(key)}Class`);
					}
				});
				allObjTypes.push({ key: `${name}_${key}`, type: 'array', info: typeInfos });
				obj[key] = typeof origin[key];
				getAllPureObject(margeArrObj, key + 'Class');
			} else if (isHasObjectArray(origin[key])) {
				let margeArrObj = {};
				for (const item of origin[key]) {
					if (isPureObject(item)) {
						margeArrObj = { ...item, ...margeArrObj };
					}
				}
				const typeInfos = new Set<string>();
				origin[key].forEach((item: any) => {
					if (typeof item !== 'object') {
						typeInfos.add(typeof item);
					} else {
						typeInfos.add(`${firstToUpperCase(key)}Class`);
					}
				});
				allObjTypes.push({ key: `${name}_${key}`, type: 'arrUnion', info: typeInfos });
				obj[key] = typeof origin[key];
				getAllPureObject(margeArrObj, key + 'Class');
			} else if (isStringArray(origin[key])) {
				allObjTypes.push({
					key: `${name}_${key}`,
					type: 'array',
					info: new Set<string>().add('string')
				});
				obj[key] = 'arr';
			} else {
				allObjTypes.push({
					key: `${name}_${key}`,
					type: 'basic',
					info: new Set<string>().add(typeof origin[key])
				});
				obj[key] = origin[key];
			}
		}
		pureObjList.push({ name, obj });
	}
	getAllPureObject(jsonData);

	console.log('pureObjList', pureObjList, allObjTypes);

	// 创建类型dom
	function createType(info: AllObjInfo) {
		const { name, obj } = info;
		resNodeList.push(
			<Suspense key={name}>
				{resNodeList.length ? <div className="divider">{'\n'}</div> : false}
				<div className="start">
					<span className="type-interface">interface </span>
					<span className="type-name">{firstToUpperCase(name)} </span>
					<span>{'{'}</span>
				</div>
				{Object.keys(obj).map((item, index) => {
					const typeInfo = allObjTypes.find((typeObj) => typeObj.key === `${name}_${item}`);
					let typeNode = null;
					if (typeInfo.type === 'basic' || typeInfo.type === 'object') {
						typeInfo.info.forEach((item) => (typeNode = <span className="type-ts">{item}</span>));
					} else if (typeInfo.type === 'arrUnion') {
						let bar = '';
						let index = 0;
						typeInfo.info.forEach((item) => {
							return (bar += index++ ? ` | ${item}` : item);
						});

						typeNode = (
							<>
								<span className="type-genericity">Array</span>
								<span>{'<'}</span>
								<span className="type-ts">{bar}</span>
								<span>{'>'}</span>
							</>
						);
					} else if (typeInfo.type === 'array') {
						typeInfo.info.forEach((item) => (typeNode = <span className="type-ts">{item}[]</span>));
					}

					return (
						<div key={index}>
							&nbsp;&nbsp;
							{/* 属性名 */}
							<span className="type-key">{item}</span>
							{/* 是否可选 */}
							{options.optional && <span className="type-optional">?</span>}
							<span className="operator">: </span>
							{/* 类型字符 */}
							{/* <span className="type-ts">
							{typeof obj[item] === 'object' ? obj[item] : typeof obj[item]}
						</span> */}
							{typeNode}
							<span>;</span>
						</div>
					);
				})}
				<div className="end">{'}'}</div>
			</Suspense>
		);
	}
	for (const item of pureObjList) {
		createType(item);
	}

	return resNodeList;
}
